package hannuota;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

//用于表示汉诺塔的柱子
// 在Tower类中，通过设置盘子数量、最大盘子宽度、最小盘子宽度和盘子高度等参数来初始化汉诺塔的状态
public class Tower extends JPanel {
    int amountOfDisc = 1;
    hannuota.Disc[] disc; //存储盘子对象。
    int maxDiscWidth, minDiscWidth, discHeight;
    char[] towerName;
    TowerPoint[] pointA;  //声明变量，表示柱子A上的位置
    TowerPoint[] pointB;
    TowerPoint[] pointC;

    AutoMoveDisc autoMoveDisc; //声明移动盘子的变量

    Tower(char[] towerName) {

        this.towerName = towerName;
        setLayout(null); //设置布局管理器为null，即手动控制组件位置
        setBackground(new Color(255, 0, 0));//设置背景颜色
    }

    public void setAmountOfDisc(int number) {
        if (number <= 1)
            amountOfDisc = 1;
        else
            amountOfDisc = number;
    }

    public void setMaxDiscWidth(int m) {

        maxDiscWidth = m;
    }

    public void setMinDiscWidth(int m) {

        minDiscWidth = m;
    }

    public void setDiscHeight(int h) {

        discHeight = h;
    }

    public hannuota.AutoMoveDisc getAutoMoveDisc() {

        return autoMoveDisc;
    }

    public void putDiscOnTower() {  //将盘子放在柱子上
        removeDisk(); //移除之前放置在柱子上的盘子。
        int n = (maxDiscWidth - minDiscWidth) / amountOfDisc; //计算每个盘子的宽度间隔
        disc = new hannuota.Disc[amountOfDisc];  //创建一个长度为amountOfDisc的Disc对象数组。
        for (int i = 0; i < disc.length; i++) {
            disc[i] = new hannuota.Disc();
            disc[i].setNumber(i); //设置盘子的编号。
            int diskwidth = minDiscWidth + i * n;//根据索引计算当前盘子的宽度,下面的disc更宽
            disc[i].setSize(diskwidth, discHeight); //设置盘子的大小
        }
        pointA = new TowerPoint[amountOfDisc]; //创建一个长度为amountOfDisc的TowerPoint对象数组，表示柱子A上的位置。
        pointB = new TowerPoint[amountOfDisc];
        pointC = new TowerPoint[amountOfDisc];
        int vertialDistance = discHeight; //设置垂直距离为盘子的高度
        for (int i = 0; i < pointA.length; i++) {  //遍历柱子A上的位置数组
            pointA[i] = new TowerPoint(maxDiscWidth, 100 + vertialDistance);
            //实例化一个新的TowerPoint对象，表示柱子A上的一个位置，并设置位置的横坐标和纵坐标
            vertialDistance = vertialDistance + discHeight;//更新垂直距离。
        }
        vertialDistance = discHeight;
        for (int i = 0; i < pointB.length; i++) {
            pointB[i] = new TowerPoint(2 * maxDiscWidth, 100 + vertialDistance);
            vertialDistance = vertialDistance + discHeight;
        }
        vertialDistance = discHeight;
        for (int i = 0; i < pointC.length; i++) {
            pointC[i] = new TowerPoint(3 * maxDiscWidth, 100 + vertialDistance);
            vertialDistance = vertialDistance + discHeight;
        }
        for (int i = 0; i < pointA.length; i++) {
            pointA[i].putDisc(disc[i], this);  //遍历柱子A上的位置数组,将盘子放置在柱子A上的一个位置上
        }

        autoMoveDisc = new hannuota.AutoMoveDisc(this); //实例化一个新的AutoMoveDisc对象，并将当前Tower对象传递给构造函数。
        autoMoveDisc.setTowerName(towerName);
        autoMoveDisc.setAmountOfDisc(amountOfDisc);
        autoMoveDisc.setPointA(pointA);
        autoMoveDisc.setPointB(pointB);
        autoMoveDisc.setPointC(pointC);
        validate();//确保容器及其所有子组件都被正确布局。如果组件或其任何子组件的大小或布局发生变化，重新验证和布局这些组件
        repaint();  //重绘组件
    }

    public void removeDisk() {   //移除所有柱子上的盘子，通过遍历柱子A、B、C上的位置数组，依次移除每个位置上的盘子
        if (pointA != null) {  //检查柱子A上的位置数组是否为null
            for (int i = 0; i < pointA.length; i++) {  //遍历柱子A上的位置数组
                pointA[i].removeDisc(pointA[i].getDiscOnPoint(), this); //调用柱子A上位置数组中第i个位置的removeDisc方法，将该位置上的盘子移除
                pointB[i].removeDisc(pointB[i].getDiscOnPoint(), this);
                pointC[i].removeDisc(pointC[i].getDiscOnPoint(), this);
            }
        }
    }
    //重写的paintComponent方法，用于在组件上绘制柱子、盘子和文字等内容
    public void paintComponent(Graphics g) {  //用于绘制柱子、盘子和文字等内容
        super.paintComponent(g);
        int x1, y1, x2, y2;
        //计算并绘制柱子A上的线段
        //获取柱子A底部盘子的x、y坐标并调整位置。
        x1 = pointA[0].getX();
        y1 = pointA[0].getY() - discHeight / 2;
        x2 = pointA[amountOfDisc - 1].getX();
        y2 = pointA[amountOfDisc - 1].getY() + discHeight / 2;
        g.drawLine(x1, y1, x2, y2);//划线,绘制从柱子A底部到顶部盘子的线段

        x1 = pointB[0].getX();
        y1 = pointB[0].getY() - discHeight / 2;
        x2 = pointB[amountOfDisc - 1].getX();
        y2 = pointB[amountOfDisc - 1].getY() + discHeight / 2;
        g.drawLine(x1, y1, x2, y2);

        x1 = pointC[0].getX();
        y1 = pointC[0].getY() - discHeight / 2;
        x2 = pointC[amountOfDisc - 1].getX();
        y2 = pointC[amountOfDisc - 1].getY() + discHeight / 2;
        g.drawLine(x1, y1, x2, y2);

        g.setColor(Color.blue);//设置绘图颜色为蓝色

        //计算矩形的位置和大小，并用蓝色填充矩形，用来表示每个柱子的底座
        x1 = pointA[amountOfDisc - 1].getX() - maxDiscWidth / 2;
        y1 = pointA[amountOfDisc - 1].getY() + discHeight / 2;
        x2 = pointC[amountOfDisc - 1].getX() + maxDiscWidth / 2;
        y2 = pointC[amountOfDisc - 1].getY() + discHeight / 2;
        int length = x2 - x1, height = 6;
        g.fillRect(x1, y1, length, height);//填充矩形

        int size = 5; //初始化一个点的大小为5，并遍历柱子A、B、C上的位置数组，绘制代表盘子的圆点
        for (int i = 0; i < pointA.length; i++) {
            //缩短 width和height  画点
            g.fillOval(pointA[i].getX() - size / 2, pointA[i].getY() - size / 2, size, size);
            g.fillOval(pointB[i].getX() - size / 2, pointB[i].getY() - size / 2, size, size);
            g.fillOval(pointC[i].getX() - size / 2, pointC[i].getY() - size / 2, size, size);
        }
        //画字符串,通过g.drawString方法在每个柱子的顶部位置绘制字符串，显示柱子的名称
        g.drawString(towerName[0] + "座", pointA[amountOfDisc - 1].getX(), pointA[amountOfDisc - 1].getY() + 50);
        g.drawString(towerName[1] + "座", pointB[amountOfDisc - 1].getX(), pointB[amountOfDisc - 1].getY() + 50);
        g.drawString(towerName[2] + "座", pointC[amountOfDisc - 1].getX(), pointC[amountOfDisc - 1].getY() + 50);
    }
}